package com.unlcn.ils.kas.service.order.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.google.common.collect.Maps;
import com.unlcn.ils.kas.dao.mapper.erp.VJmcKasFlowInfoMapper;
import com.unlcn.ils.kas.dao.mapper.erp.VJmcKasOnwayTrackMapper;
import com.unlcn.ils.kas.dao.model.erp.VJmcKasFlowInfo;
import com.unlcn.ils.kas.dao.model.erp.VJmcKasOnwayTrack;
import com.unlcn.ils.kas.dao.model.order.Customer;
import com.unlcn.ils.kas.dao.model.order.OrderOtd;
import com.unlcn.ils.kas.dao.model.order.OrderOtdDetail;
import com.unlcn.ils.kas.dao.model.order.OrderOtdException;
import com.unlcn.ils.kas.dao.model.order.OrderOtdLog;
import com.unlcn.ils.kas.dao.model.order.OrderOtdLogDetail;
import com.unlcn.ils.kas.dao.model.order.PushOrderLog;
import com.unlcn.ils.kas.service.erp.impl.VJmcKasFlowInfoServiceImpl;
import com.unlcn.ils.kas.service.map.BaiDuMap.util.BaiDuMapGeocodeUtil;
import com.unlcn.ils.kas.service.map.BaiDuMap.util.BaiDuMapRouteUtil;
import com.unlcn.ils.kas.service.order.CustomerService;
import com.unlcn.ils.kas.service.order.OrderOtdDetailService;
import com.unlcn.ils.kas.service.order.OrderOtdExceptionService;
import com.unlcn.ils.kas.service.order.OrderOtdService;
import com.unlcn.ils.kas.service.order.PushOrderLogService;
import com.unlcn.ils.kas.service.order.SharesOrderService;
import com.unlcn.ils.kas.service.util.ErpUrl;
import com.unlcn.ils.kas.service.util.HttpClientUtil;
import com.unlcn.ils.kas.service.util.enums.order.CustomNoEnum;
import com.unlcn.ils.kas.service.util.enums.order.OrderDetailDeleteFlagEnum;
import com.unlcn.ils.kas.service.util.enums.order.OrderDetailIsmanualEnum;
import com.unlcn.ils.kas.service.util.enums.order.OrderOtdExceptionEnum;
import com.unlcn.ils.kas.service.util.enums.order.OrderWayEnum;
import com.unlcn.ils.kas.service.util.enums.order.PushOrderLogTypeEnum;

import com.unlcn.ils.kas.service.util.DateUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.apache.poi.util.StringUtil;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

/**
 * 江铃股份订单调度 service 实现
 *
 * @author 罗必量
 */
@Component
public class SharesOrderServiceImpl implements SharesOrderService {

    private static final Logger LOGGER = LoggerFactory.getLogger(SharesOrderServiceImpl.class);

    /**
     * 订单在途跟踪 service
     */
    @Autowired
    private OrderOtdService orderOtdService;

    /**
     * 订单在途跟踪明细 service
     */
    @Autowired
    private OrderOtdDetailService orderOtdDetailService;

    /**
     * 客户 service
     */
    @Autowired
    private CustomerService customerService;

    /**
     * 执行日志 service
     */
    @Autowired
    private PushOrderLogService pushOrderLogService;

    /**
     * 拉取订单异常 service
     */
    @Autowired
    private OrderOtdExceptionService orderOtdExceptionService;

    /**
     * erp 接口地址 model
     */
    @Autowired
    private ErpUrl erpUrl;

    /**
     * v_jmc_kas_onway_track中间表 mapper
     */
    @Autowired
    private VJmcKasOnwayTrackMapper vJmcKasOnwayTrackMapper;
    /**
     * v_jmc_kas_flow_info中间表 mapper
     */
    @Autowired
    private VJmcKasFlowInfoMapper vJmcKasFlowInfoMapper;
    /**
     *
     */
    @Autowired
    private VJmcKasFlowInfoServiceImpl vJmcKasFlowInfoService;

    /**
     * 获取订单详情、订单在途信息 定时任务
     */
    @Override
    public void getOrder() {
        LOGGER.info("拉取股份订单====================");
        PushOrderLog pushOrderLog = new PushOrderLog();
        Integer executNum = 0; // 已经执行的数量
        Integer insertNum = 0; // 插入数
        Integer updateNum = 0; // 更新数
        Integer abnormalNum = 0; // 异常数

        // 获取线程名称
        String pushThreadName = Thread.currentThread().getName();
        pushOrderLog.setPushThreadName(pushThreadName);
        // 拉取控股订单（记录拉取日志）
        pushOrderLog.setType(PushOrderLogTypeEnum.GF.getCode());
        // 开始执行时间
        pushOrderLog.setStartExecutTime(new Date());

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        Date startTime = null;
        Date endTime = null;
        try {
            startTime = pushOrderLogService.getLastTime(PushOrderLogTypeEnum.GF.getCode());
            if (startTime == null) {
                DateTime dt = new DateTime();
                Integer year = dt.getYear();
                Integer month = dt.getMonthOfYear();
                int day = dt.getDayOfMonth() - 1;
                startTime = new DateTime(year, month, day, 0, 0, 0).toDate();
            }
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(startTime);
            calendar.add(Calendar.DAY_OF_MONTH, 1);
            // calendar.add(Calendar.HOUR_OF_DAY,8);
            endTime = calendar.getTime();
        } catch (Exception e) {
            LOGGER.error("SharesOrderServiceImpl.getOrder(获取拉取股份订单时间区间异常)： params {} ", e);
        }

        List<NameValuePair> orderParams = new ArrayList<>();
        orderParams.add(new BasicNameValuePair("icustomerid", CustomNoEnum.GF.getValue()));
        orderParams.add(new BasicNameValuePair("startTime", simpleDateFormat.format(startTime)));
        orderParams.add(new BasicNameValuePair("endTime", simpleDateFormat.format(endTime)));
        Date callStartTime = new Date();
        String getOrderNoResult = HttpClientUtil.get(erpUrl.getGetErpGfOrderNo(), orderParams, 600000000);
        Date callEndTime = new Date();
        if (StringUtils.isEmpty(getOrderNoResult))
            return;

        // 将订单号转换成map集合
        List<Map> orderMapNoList = getMap(getOrderNoResult);
        LOGGER.info(simpleDateFormat.format(new Date()) + "拉取了" + orderMapNoList.size() + "条订单(股份)");

        // 拉取数量
        pushOrderLog.setDataNum(orderMapNoList.size());

        if (orderMapNoList == null) {
            // 完成时间
            pushOrderLog.setFinshExecutTime(new Date());
            // 记录执行日志
            pushOrderLogService.insert(pushOrderLog);
            return;
        }

        // 遍历转换成的mao，一一存储进数据库
        LOGGER.info("(股份)遍历" + orderMapNoList.size() + "条订单");
        for (int i = 0; orderMapNoList.size() > i; i++) {

            LOGGER.info("遍历第" + i + "条订单");

            Map map = orderMapNoList.get(i);

            String vcdn = map.get("vcdn").toString();

            try {
                // 获取订单详情
                List<NameValuePair> orderDetailParams = new ArrayList<>();
                orderDetailParams.add(new BasicNameValuePair("vcdn", vcdn));
                String getOrderDetailResult = HttpClientUtil.get(erpUrl.getGetErpOrderDetail(), orderDetailParams,
                        600000000);
                LOGGER.info("(" + vcdn + ")获取订单详情接口返回信息: ", getOrderDetailResult);
                if (StringUtils.isEmpty(getOrderDetailResult))
                    continue;

                JSONObject json = JSONObject.parseObject(getOrderDetailResult);
                Object obj = json.get("data");
                LOGGER.info("(" + vcdn + ")" + "详情: " + obj);
                if (obj == null)
                    continue;
                OrderOtdLog orderOtdLog = analysisOrder((Map) obj);
                orderOtdLog.setCallUrl(erpUrl.getGetErpKgOrderNo());
                orderOtdLog.setCallStartTime(callStartTime);
                orderOtdLog.setCallEndTime(callEndTime);

                // 获取定在在途信息
                List<NameValuePair> onWayParams = new ArrayList<>();
                onWayParams.add(new BasicNameValuePair("vcdn", orderOtdLog.getSysOrderNo()));
                String onWayResult = HttpClientUtil.get(erpUrl.getGetErpOnway(), onWayParams, 600000000);

                List<OrderOtdLogDetail> orderOtdLogDetailList = new ArrayList<>();
                if (!StringUtils.isEmpty(onWayResult)) {
                    // 将在途信息转换成map集合
                    List<Map> onWayList = getMap(onWayResult);

                    if (!CollectionUtils.isEmpty(onWayList)) {
                        for (Map onWayMap : onWayList) {
                            OrderOtdLogDetail orderOtdLogDetail = analysisOnWayInfo(onWayMap);
                            orderOtdLogDetailList.add(orderOtdLogDetail);
                        }
                    }
                }

                // 保存订单详细信息、在途信息
                String executWay = saveOrderInfo(orderOtdLog, orderOtdLogDetailList);

                if (executWay.equals("insert")) {
                    insertNum++;
                    pushOrderLog.setInsertNum(insertNum);
                } else if (executWay.equals("update")) {
                    updateNum++;
                    pushOrderLog.setUpdateNum(updateNum);
                }
                executNum++;
                pushOrderLog.setExecutNum(executNum);
                List<PushOrderLog> pushOrderLogList = pushOrderLogService
                        .selectNowDay(PushOrderLogTypeEnum.GF.getCode(), pushThreadName);
                if (CollectionUtils.isEmpty(pushOrderLogList)) {
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.insert(pushOrderLog);
                } else {
                    pushOrderLog.setId(pushOrderLogList.get(0).getId());
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.updateById(pushOrderLog);
                }
            } catch (Exception e) {
                LOGGER.error("拉取订单" + vcdn + "发生异常", e);

                // 保存异常信息
                OrderOtdException orderOtdException = new OrderOtdException();
                orderOtdException.setSysOrderCode(vcdn);
                orderOtdException.setExceptionMsg(JSON.toJSONString(e));
                orderOtdException.setFlag(OrderOtdExceptionEnum.UNTREATED.getCode());
                orderOtdException.setGmtCreate(new Date());
                saveOrderException(orderOtdException);

                abnormalNum++;
                executNum++;
                pushOrderLog.setAbnormalNum(abnormalNum);
                pushOrderLog.setExecutNum(executNum);

                List<PushOrderLog> pushOrderLogList = pushOrderLogService
                        .selectNowDay(PushOrderLogTypeEnum.GF.getCode(), pushThreadName);
                if (CollectionUtils.isEmpty(pushOrderLogList)) {
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.insert(pushOrderLog);
                } else {
                    pushOrderLog.setId(pushOrderLogList.get(0).getId());
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.updateById(pushOrderLog);
                }

                continue;
            }
        }
    }

    /* @author:罗必量 */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public String saveOrderInfo(OrderOtdLog orderOtdLog, List<OrderOtdLogDetail> orderOtdLogDetailList) {

        String executWay = null;

        // 保存在途跟踪日志表
        orderOtdLog.setGmtCreate(new Date());

        // 保存在途跟踪日志明细信息
        for (int i = 0; orderOtdLogDetailList.size() > i; i++) {
            orderOtdLogDetailList.get(i).setHeadId(orderOtdLog.getId());
        }

        // 校验订单是否已经存在 kas 订单跟踪表
        EntityWrapper<OrderOtd> ew = new EntityWrapper<>();
        ew.eq("sys_order_no", orderOtdLog.getSysOrderNo());
        List<OrderOtd> orderOtdList = orderOtdService.selectList(ew);

        // 转换跟踪订单
        OrderOtd orderOtd = transformation(orderOtdLog, orderOtdList);

        // 存在则更新，否则插入
        if (!CollectionUtils.isEmpty(orderOtdList)) {
            orderOtd.setId(orderOtdList.get(0).getId());
            orderOtd.setGmtCreate(orderOtdList.get(0).getGmtCreate());
            orderOtd.setGmtModified(new Date());
            // 如果订单在kas里已经存在 运抵时间||回单时间，则不更新
            if (orderOtdList.get(0).getShiptoTime() == null && orderOtdList.get(0).getReturnOrderTime() == null) {
                // 保存在途跟踪明细信息
                LOGGER.info(orderOtdLogDetailList.size() + "条在途信息");
                saveDetail(orderOtd, orderOtdLogDetailList);
            }

            // 更新在途跟踪表
            if (isNotRequireUpdate(orderOtdList)) {
                // 当数据更新途径不为ERP(为手工或excel导入)且运抵时间不为空时,不更新数据
                LOGGER.info("(" + orderOtd.getSysOrderNo() + ")不可自动更新");
                executWay = "ignore";
            } else {
                orderOtdService.updateById(orderOtd);
                LOGGER.info("(" + orderOtd.getSysOrderNo() + ")成功更新订单");
                executWay = "update";
            }
        } else {
            // 保存在途跟踪表
            orderOtd.setGmtCreate(new Date());
            orderOtdService.insert(orderOtd);
            LOGGER.info("(" + orderOtd.getSysOrderNo() + ")成功插入订单");

            orderOtdList = orderOtdService.selectList(ew);
            orderOtd = orderOtdList.get(0);
            // 保存在途跟踪明细信息
            LOGGER.info(orderOtdLogDetailList.size() + "条在途信息");
            saveDetail(orderOtd, orderOtdLogDetailList);

            executWay = "insert";
        }
        if (!"ignore".equalsIgnoreCase(executWay)) {
            // 添加计算预计运抵时间的模块
            updateNewestPositionRelInfo(orderOtd.getSysOrderNo());
        }
        return executWay;
    }

    // 更新主表的最新位置,最新在途时间，预计运抵时间
    @Transactional(propagation = Propagation.REQUIRED)
    public void updateNewestPositionRelInfo(String sysOrderNo) {
        OrderOtd orderOtd = orderOtdService.selectOne(new EntityWrapper<OrderOtd>().eq("sys_order_no", sysOrderNo));
        Wrapper<OrderOtdDetail> wrapper = new EntityWrapper<>();
        wrapper.eq("sys_order_no", sysOrderNo);
        wrapper.orderBy("track_time", false);
        List<OrderOtdDetail> onwayDetail = orderOtdDetailService.selectList(wrapper);

        String endAddress = orderOtd.getdProvince() + orderOtd.getdCity();
        if (!StringUtils.isEmpty(orderOtd.getShiptoTime())) {
            orderOtd.setNewestPosition(endAddress);
            orderOtd.setNewestTime(orderOtd.getShiptoTime());
        } else if (!StringUtils.isEmpty(orderOtd.getManualShiptoTime())) {
            orderOtd.setNewestPosition(endAddress);
            orderOtd.setNewestTime(orderOtd.getManualShiptoTime());
        } else if (!CollectionUtils.isEmpty(onwayDetail)) {
            // 获取最新在途
            OrderOtdDetail newestOnway = onwayDetail.get(0);
            if (!StringUtils.isEmpty(newestOnway)) {
                String newestPosition = (StringUtils.isEmpty(newestOnway.getProvince()) ? ""
                        : newestOnway.getProvince() + "-")
                        + (StringUtils.isEmpty(newestOnway.getCity()) ? "" : newestOnway.getCity() + "-")
                        + (StringUtils.isEmpty(newestOnway.getArea()) ? "" : newestOnway.getArea() + "-")
                        + (StringUtils.isEmpty(newestOnway.getAddress()) ? "" : newestOnway.getAddress());
                orderOtd.setNewestPosition(newestPosition);
                orderOtd.setNewestTime(newestOnway.getTrackTime());
            }
        }

        if (!StringUtils.isEmpty(orderOtd.getShiptoTime())) {
            orderOtd.setPlanShiptoTime(orderOtd.getShiptoTime());
        } else if (!StringUtils.isEmpty(orderOtd.getManualShiptoTime())) {
            orderOtd.setPlanShiptoTime(orderOtd.getManualShiptoTime());
        } else {
            // 计算预计送达时间
            orderOtd.setPlanShiptoTime(this.expectedArrivalTime(orderOtd));
        }

        if (StringUtils.isEmpty(orderOtd.getInboundTime()) && StringUtils.isEmpty(orderOtd.getArrangeCapacityTime())) {
            orderOtd.setPlanShiptoTime(null);
        }
        orderOtd.setGmtModified(new Date());
        orderOtdService.updateById(orderOtd);
    }

    /*
     * @author:罗必量 保存在途轨迹明细
     */
    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public void saveDetail(OrderOtd orderOtd, List<OrderOtdLogDetail> orderOtdLogDetailList) {
        LOGGER.info("[" + orderOtd.getSysOrderNo() + "]" + orderOtdLogDetailList.size() + "条在途信息");

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 保存在途跟踪明细信息
        for (OrderOtdLogDetail orderOtdLogDetail : orderOtdLogDetailList) {

            // 不保存重复在途信息
            Wrapper<OrderOtdDetail> detailEntity = new EntityWrapper<OrderOtdDetail>();
            detailEntity.eq("tid", orderOtdLogDetail.gettId());
            List<OrderOtdDetail> orderOtdDetails = orderOtdDetailService.selectList(detailEntity);
            if (CollectionUtils.isEmpty(orderOtdDetails)) {
                detailEntity = new EntityWrapper<OrderOtdDetail>();
                detailEntity.eq("track_time", simpleDateFormat.format(orderOtdLogDetail.getTrackTime()));
                detailEntity.eq("sys_order_no", orderOtdLogDetail.getSysOrderNo());
                orderOtdDetails = orderOtdDetailService.selectList(detailEntity);
            }
            if (!CollectionUtils.isEmpty(orderOtdDetails)) {
                continue;
            }

            OrderOtdDetail orderOtdDetail = new OrderOtdDetail();
            BeanUtils.copyProperties(orderOtdLogDetail, orderOtdDetail);

            orderOtdDetail.setHeadId(orderOtd.getId());

            // 计算运输距离
            Number distance = computationalDistance(orderOtd, orderOtdDetail);
            orderOtdDetail.setDistance(distance.floatValue());

            // 查看是否存在比该在途数据定位时间更早,离目的地更近的手工维护轨迹点,有则该条在途数据视为不合法,跳过(扩展,如果该数据计算剩余距离时百度异常,剩余距离视为0,肯定能被视为合法)
            Wrapper<OrderOtdDetail> wrapper = new EntityWrapper<>();
            wrapper.eq("sys_order_no", orderOtdDetail.getSysOrderNo());
            wrapper.eq("ismanual", OrderDetailIsmanualEnum.YES.getCode());
            wrapper.lt("track_time", simpleDateFormat.format(orderOtdDetail.getTrackTime()));
            wrapper.lt("distance", orderOtdDetail.getDistance());
            wrapper.eq("isdelete", OrderDetailDeleteFlagEnum.NORMAL.getCode());
            if (!CollectionUtils.isEmpty(orderOtdDetailService.selectList(wrapper))) {
                continue;
            }

            orderOtdDetailService.insert(orderOtdDetail);
        }
    }

    /**
     * 计算剩余运输距离
     * 
     * @author: 罗必量
     * @param orderOtd
     * @param orderOtdDetail
     * @return
     */
    @Override
    public Number computationalDistance(OrderOtd orderOtd, OrderOtdDetail orderOtdDetail) {

        Number distance = 0.00;

        if (orderOtdDetail == null)
            return distance;

        if (orderOtdDetail.getLatitude() == null || orderOtdDetail.getLongitude() == null) {
            // 计算运输距离
            String startAddress = orderOtdDetail.getProvince() + orderOtdDetail.getCity() + orderOtdDetail.getArea()
                    + orderOtdDetail.getAddress();
            String endAddress = orderOtd.getdProvince() + orderOtd.getdCity() + orderOtd.getdAddress();
            distance = getDistance(startAddress, endAddress);
        } else {
            Map<String, Double> mapOrgrin = Maps.newHashMap();
            mapOrgrin.put("lat", Double.valueOf(orderOtdDetail.getLatitude().toString()));
            mapOrgrin.put("lng", Double.valueOf(orderOtdDetail.getLongitude().toString()));

            String cords = mapOrgrin.get("lng") + "," + mapOrgrin.get("lat");
            List<Map<String, Double>> lists = BaiDuMapGeocodeUtil.geoConv(cords, 1, 5);
            if (!CollectionUtils.isEmpty(lists)) {
                Map<String, Double> mapGeo = lists.get(0);

                String destination = null;

                // 根据详细地址获取距离
                destination = orderOtd.getdAddress();
                Map<String, Double> mapDestinations = BaiDuMapGeocodeUtil.addressToGPS(destination);
                if (null == mapDestinations || StringUtils.isEmpty(mapDestinations.get("lat"))
                        || StringUtils.isEmpty(mapDestinations.get("lng"))) {
                    distance = null;
                } else {
                    distance = BaiDuMapRouteUtil.getDistance(mapGeo, mapDestinations) / 1000;
                }

                // 如果详细地址无法获取距离，则根据省市区加详细地址
                if (distance == null || 0 >= distance.doubleValue()) {
                    destination = orderOtd.getdProvince() + orderOtd.getdCity() + orderOtd.getdAddress();
                    destination = destination.replaceAll("null", "");
                    mapDestinations = BaiDuMapGeocodeUtil.addressToGPS(destination);
                    if (null == mapDestinations || StringUtils.isEmpty(mapDestinations.get("lat"))
                            || StringUtils.isEmpty(mapDestinations.get("lng"))) {
                        distance = 0.00;
                    } else {
                        distance = BaiDuMapRouteUtil.getDistance(mapGeo, mapDestinations) / 1000;
                    }
                }
            }
        }

        return null == distance ? 0.00 : distance;
    }

    /* @author:罗必量 */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    @Override
    public void saveOrderException(OrderOtdException orderOtdException) {
        orderOtdExceptionService.insert(orderOtdException);
    }

    /**
     * 转换跟踪订单
     * 
     * @author:罗必量
     * @param orderOtdLog
     * @param orderOtdList
     * @return
     */
    @Override
    public OrderOtd transformation(OrderOtdLog orderOtdLog, List<OrderOtd> orderOtdList) {
        String dn = orderOtdLog.getSysOrderNo();

        System.out.println("订单号:" + dn);
        OrderOtd orderOtd = null;
        orderOtd = new OrderOtd();
        if (!CollectionUtils.isEmpty(orderOtdList) && !StringUtils.isEmpty(orderOtdList.get(0))) {
            BeanUtils.copyProperties(orderOtdList.get(0), orderOtd);
        }

        BeanUtils.copyProperties(orderOtdLog, orderOtd);

        // 查询客户编号
        EntityWrapper<Customer> customerEntity = new EntityWrapper<>();
        customerEntity.eq("name", orderOtd.getCustomerName());
        List<Customer> customerList = customerService.selectList(customerEntity);
        if (!CollectionUtils.isEmpty(customerList)) {
            orderOtd.setCustomerNo(customerList.get(0).getCode());
        }

        // 数据源
        orderOtd.setWay(OrderWayEnum.WAY_SYS_INTF.getCode());

        // 计算起运地到目的地的距离
        String startAddress = orderOtd.getoProvince() + orderOtd.getoCity() + orderOtd.getoAddress();
        String endAddress = orderOtd.getdProvince() + orderOtd.getdCity() + orderOtd.getdAddress();

        if (StringUtils.isEmpty(orderOtd.getDistance()) || orderOtd.getDistance() == 0) {
            orderOtd.setDistance(getDistance(startAddress, endAddress).floatValue());
        }

        // 判断挂起状态
        if (orderOtd.getBsuspend() != null) {
            // 0正常订单；1挂起订单
            if (orderOtd.getBsuspend() == 0) {
                // 如果 kas 手动司机联系方式不为空，则更新 tms 同步信息
                if (!CollectionUtils.isEmpty(orderOtdList)
                        && !StringUtils.isEmpty(orderOtdList.get(0).getManualDriverPhone())) {
                    orderOtd.setDriverPhone(orderOtdList.get(0).getManualDriverPhone());
                } else {
                    orderOtd.setDriverPhone(orderOtdLog.getDriverPhone());
                }
                // 如果 kas 手动运抵时间不为空，则更新 tms 同步信息
                if (!CollectionUtils.isEmpty(orderOtdList)
                        && !StringUtils.isEmpty(orderOtdList.get(0).getManualShiptoTime())) {
                    orderOtd.setShiptoTime(orderOtdList.get(0).getManualShiptoTime());
                } else {
                    orderOtd.setShiptoTime(orderOtdLog.getShiptoTime());
                }
            } else if (orderOtd.getBsuspend() == 1) {
                orderOtd.setManualDriverPhone(null);
                orderOtd.setManualShiptoTime(null);
                orderOtd.setShiptoTime(null);
            }
        }

        // 判断订单状态
        if (orderOtd.getLeaveTime() == null) {
            orderOtd.setOrderStatus("未离昌");
        }
        if (orderOtd.getLeaveTime() != null) {
            orderOtd.setOrderStatus("在途");
        }
        if (orderOtd.getShiptoTime() != null) {
            orderOtd.setOrderStatus("交付");
        }

        return orderOtd;
    }

    private Date getTodayDate() {
        Calendar calToday = Calendar.getInstance();
        Date now = new Date();
        calToday.setTime(now);
        int year = calToday.get(Calendar.YEAR);
        int month = calToday.get(Calendar.MONTH);
        int day = calToday.get(Calendar.DAY_OF_MONTH);
        calToday.set(year, month, day);
        return calToday.getTime();
    }

    /**
     * 计算距离和预计送达时间
     * 
     * @author:罗必量
     * @param orderOtd
     * @return
     */
    @Override
    public Date expectedArrivalTime(OrderOtd orderOtd) {
        if (orderOtd == null) {
            return null;
        }
        Date today = getTodayDate();
        // 离昌前
        if (StringUtils.isEmpty(orderOtd.getLeaveTime())) {
            // 未安排运力并未入中联库，预计送达时间为空
            if (StringUtils.isEmpty(orderOtd.getInboundTime())
                    && StringUtils.isEmpty(orderOtd.getArrangeCapacityTime())) {
                return null;
            } else if (!StringUtils.isEmpty(orderOtd.getArrangeCapacityTime())) {
                // 已安排运力，预计送达时间=安排时间+在途时效+流转时间
                Double distance = orderOtd.getDistance().doubleValue();
                Double timeLimitation = 0.00;
                Double circulationTime = 0.00;

                if (orderOtd.getTransportType().lastIndexOf("三位") >= 0
                        || orderOtd.getTransportType().lastIndexOf("四位") >= 0) {
                    // 三位板在途时效
                    timeLimitation = distance / 550;
                    // 三位板流转时间
                    circulationTime = 0.0;
                } else if (orderOtd.getTransportType().lastIndexOf("人送") >= 0) {
                    // 人送在途时效
                    timeLimitation = distance / 550;
                    // 人送流转时间
                    circulationTime = 0.5;
                } else if (orderOtd.getTransportType().lastIndexOf("铁") >= 0) {
                    // 铁运在途时效
                    timeLimitation = distance / 250;
                    // 铁运流转时间
                    circulationTime = 2.0;
                } else if (orderOtd.getTransportType().lastIndexOf("水") >= 0) {
                    // 水运在途时效
                    timeLimitation = distance / 185;
                    // 水运流转时间
                    circulationTime = 2.0;
                } else {
                    // 默认按零公里在途时效
                    timeLimitation = distance / 550;
                    // 零公里流转时间
                    circulationTime = 1.0;
                }

                Calendar calendar = Calendar.getInstance();
                // 安排运力时间
                calendar.setTime(orderOtd.getArrangeCapacityTime());
                // 加上在途时效
                Number limitation = Math.ceil(timeLimitation) * 24;
                calendar.add(Calendar.HOUR_OF_DAY, limitation.intValue());
                // 加上流转时间
                Number circulation = circulationTime * 24;
                calendar.add(Calendar.HOUR_OF_DAY, circulation.intValue());

                if (calendar.getTime().before(today)) {
                    calendar.setTime(today);
                    calendar.add(Calendar.HOUR_OF_DAY, limitation.intValue());
                    calendar.add(Calendar.HOUR_OF_DAY, circulation.intValue());
                }
                return calendar.getTime();
            } else {
                // 未安排运力则以入库时间推预计离昌时间,然后再推预计运抵时间
                // 预计送达时间=入库时间+预计离昌时间+在途时效+流转时间
                Double distance = orderOtd.getDistance().doubleValue();
                Double timeLimitation = 0.00;
                Double circulationTime = 0.00;
                // 暂时写死预计离昌时间三天
                Double fakeLeaveDays = 3.0;
                // 默认按零公里在途时效
                timeLimitation = distance / 550;
                // 零公里流转时间
                circulationTime = 1.0;

                Calendar calendar = Calendar.getInstance();
                // 安排运力时间
                calendar.setTime(orderOtd.getInboundTime());
                // 加上预计离昌天数
                calendar.add(Calendar.DAY_OF_MONTH, fakeLeaveDays.intValue());
                // 加上在途时效
                Number limitation = Math.ceil(timeLimitation) * 24;
                calendar.add(Calendar.HOUR_OF_DAY, limitation.intValue());
                // 加上流转时间
                Number circulation = circulationTime * 24;
                calendar.add(Calendar.HOUR_OF_DAY, circulation.intValue());

                if (calendar.getTime().before(today)) {
                    calendar.setTime(today);
                    calendar.add(Calendar.HOUR_OF_DAY, limitation.intValue());
                    calendar.add(Calendar.HOUR_OF_DAY, circulation.intValue());
                }
                return calendar.getTime();
            }
        } else {
            // 计算剩余公里数
            String startAddress = orderOtd.getNewestPosition();
            String endAddress = orderOtd.getdProvince() + orderOtd.getdCity() + orderOtd.getdAddress();
            Double distance = getDistance(startAddress, endAddress);
            if (distance == null || distance.compareTo(0d) == 0) {
                distance = 0d;
            }
            int limitation = calcRestOnwayHours(distance, orderOtd.getTransportType());
            // 加上时效，算出预计送达时间

            Calendar calendar = Calendar.getInstance();
            if (orderOtd.getNewestTime() == null) {
                calendar.setTime(today);
            } else {
                calendar.setTime(orderOtd.getNewestTime());
            }
            if (limitation == 0) {
                if (!StringUtils.isEmpty(orderOtd.getPlanShiptoTime())) {
                    calendar.setTime(orderOtd.getPlanShiptoTime());
                } else {
                    calendar.setTime(orderOtd.getLeaveTime());
                    calendar.add(Calendar.HOUR_OF_DAY,
                            calcRestOnwayHours(orderOtd.getDistance(), orderOtd.getTransportType()));
                }
            } else {
                calendar.add(Calendar.HOUR_OF_DAY, limitation);
            }

            if (calendar.getTime().before(today)) {
                Date oldPlanShipToTime = calendar.getTime();
                calendar.setTime(today);
                if (limitation == 0) {
                    int hoursInterval = 0;
                    if (!StringUtils.isEmpty(orderOtd.getNewestTime())) {
                        hoursInterval = DateUtils.hoursBetween(orderOtd.getNewestTime(), oldPlanShipToTime);
                    } else {
                        hoursInterval = DateUtils.hoursBetween(orderOtd.getLeaveTime(), oldPlanShipToTime);
                    }
                    calendar.add(Calendar.HOUR_OF_DAY, hoursInterval);
                } else {
                    calendar.add(Calendar.HOUR_OF_DAY, limitation);
                }
            }
            return calendar.getTime();
        }
    }

    /**
     * 根据在途后的剩余公里数计算剩余在途小时数取整
     * 
     * @param remainDistance
     * @param transportMode
     * @return
     */
    public int calcRestOnwayHours(double remainDistance, String transportMode) {
        Number limitation;
        if (StringUtils.isEmpty("transportMode")) {
            transportMode = "零公里";
        }
        if (transportMode.lastIndexOf("人送") >= 0) {
            // 人送
            limitation = Math.ceil(remainDistance / 550) * 24;
        } else if (transportMode.lastIndexOf("铁") >= 0) {
            // 铁运
            limitation = Math.ceil(remainDistance / 250) * 24 + (24) * 3;
        } else if (transportMode.lastIndexOf("水") >= 0) {
            // 水运
            limitation = Math.ceil(remainDistance / 185) * 24 + (24) * 3;
        } else {
            limitation = Math.ceil(remainDistance / 550) * 24;
        }
        return limitation.intValue();
    }

    /**
     * 获取两地距离
     * 
     * @author:罗必量
     * @param startAddress
     * @param endAddress
     * @return
     */
    @Override
    public Double getDistance(String startAddress, String endAddress) {
        if (StringUtils.isEmpty(startAddress) || StringUtils.isEmpty(endAddress))
            return 0.0;

        startAddress = startAddress.replaceAll("null", "");
        endAddress = endAddress.replaceAll("null", "");

        Double distance = 0.0;
        try {
            distance = BaiDuMapRouteUtil.getDistance(startAddress, endAddress);
        } catch (Exception e) {
            distance = 0.0;
        }
        distance = distance / 1000;

        return distance;
    }

    /**
     * 将ResponseEntity结果转换成map集合
     *
     * @author:罗必量
     * @param result
     * @return
     */
    @Override
    public List<Map> getMap(String result) {

        List<Map> dataMapList = new ArrayList<Map>();

        JSONObject json = JSONObject.parseObject(result);

        if (json == null || json.get("data") == null)
            return dataMapList;

        JSONArray jsonArray = JSONArray.parseArray(json.get("data").toString());

        if (jsonArray == null || jsonArray.size() == 0)
            return dataMapList;

        // 遍历订单JSON串，一一转换成map
        for (Object obj : jsonArray) {
            Map map = (Map) obj;
            dataMapList.add(map);
        }

        return dataMapList;
    }

    /**
     * 格式化在途信息
     *
     * @author:罗必量
     * @param map
     * @return
     */
    @Override
    public OrderOtdLogDetail analysisOnWayInfo(Map map) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        OrderOtdLogDetail orderOtdLogDetail = new OrderOtdLogDetail();
        if (map == null)
            return orderOtdLogDetail;

        try {
            // 明细 id
            if (!StringUtils.isEmpty(map.get("tid"))) {
                orderOtdLogDetail.settId(map.get("tid").toString());
            }
            // 在途时间
            if (!StringUtils.isEmpty(map.get("dtlocation"))) {
                orderOtdLogDetail.setTrackTime(simpleDateFormat.parse(map.get("dtlocation").toString()));
            }
            // 所在省
            if (!StringUtils.isEmpty(map.get("vcprovince"))) {
                orderOtdLogDetail.setProvince(map.get("vcprovince").toString());
            }
            // 所在市
            if (!StringUtils.isEmpty(map.get("vccity"))) {
                orderOtdLogDetail.setCity(map.get("vccity").toString());
            }
            // 所在区/县
            if (!StringUtils.isEmpty(map.get("vcarea"))) {
                orderOtdLogDetail.setArea(map.get("vcarea").toString());
            }
            // 详细地址
            if (!StringUtils.isEmpty(map.get("vclocation"))) {
                orderOtdLogDetail.setAddress(map.get("vclocation").toString());
            }
            // 经度
            if (!StringUtils.isEmpty(map.get("vclongitude"))) {
                orderOtdLogDetail.setLongitude(new BigDecimal(map.get("vclongitude").toString()));
            }
            // 纬度
            if (!StringUtils.isEmpty(map.get("vclatitude"))) {
                orderOtdLogDetail.setLatitude(new BigDecimal(map.get("vclatitude").toString()));
            }
            // 系统订单号
            if (!StringUtils.isEmpty(map.get("vcdn"))) {
                orderOtdLogDetail.setSysOrderNo(map.get("vcdn").toString());
            }
        } catch (Exception e) {
            LOGGER.error("OrderScheduled.analysisOnWayInfo ERROR: ", e);
        }

        return orderOtdLogDetail;
    }

    /**
     * 格式化订单
     *
     * @author:罗必量
     * @param map
     * @return
     */
    @Override
    public OrderOtdLog analysisOrder(Map map) {

        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        OrderOtdLog orderOtdLog = new OrderOtdLog();
        if (map == null)
            return orderOtdLog;

        try {
            // 离昌时间
            if (!StringUtils.isEmpty(map.get("dtonway"))) {
                orderOtdLog.setLeaveTime(simpleDateFormat.parse(map.get("dtonway").toString()));
            }
            // 安排运力时间
            if (!StringUtils.isEmpty(map.get("dtassign"))) {
                orderOtdLog.setArrangeCapacityTime(simpleDateFormat.parse(map.get("dtassign").toString()));
            }
            // 入铁路库时间
            if (!StringUtils.isEmpty(map.get("dt2rail"))) {
                orderOtdLog.setEnterRailwayTime(simpleDateFormat.parse(map.get("dt2rail").toString()));
            }
            // 入中转库时间
            if (!StringUtils.isEmpty(map.get("dtcache"))) {
                orderOtdLog.setInboundTime(simpleDateFormat.parse(map.get("dtcache").toString()));
            }
            // 订单创建时间
            if (!StringUtils.isEmpty(map.get("dtcreate"))) {
                orderOtdLog.setOrderCreateTime(simpleDateFormat.parse(map.get("dtcreate").toString()));
            }
            // 运抵时间
            if (!StringUtils.isEmpty(map.get("dtdelivery"))) {
                orderOtdLog.setShiptoTime(simpleDateFormat.parse(map.get("dtdelivery").toString()));
            }
            // 最新在途时间
            if (!StringUtils.isEmpty(map.get("dtlocation"))) {
                orderOtdLog.setNewestTime(simpleDateFormat.parse(map.get("dtlocation").toString()));
            }
            // 订单日期
            if (!StringUtils.isEmpty(map.get("dtorder"))) {
                orderOtdLog.setOrderDate(simpleDateFormat.parse(map.get("dtorder").toString()));
            }
            // 出中联库时间
            if (!StringUtils.isEmpty(map.get("dtout_3pl"))) {
                orderOtdLog.setOutboundTime(simpleDateFormat.parse(map.get("dtout_3pl").toString()));
            }
            // 提车时间
            if (!StringUtils.isEmpty(map.get("dtout_factory"))) {
                orderOtdLog.setPickTime(simpleDateFormat.parse(map.get("dtout_factory").toString()));
            }
            // 装车时间
            if (!StringUtils.isEmpty(map.get("dtload"))) {
                orderOtdLog.setLoadTime(simpleDateFormat.parse(map.get("dtload").toString()));
            }
            // 客户编号
            if (!StringUtils.isEmpty(map.get("icustomerid"))) {
                orderOtdLog.setCustomerNo(map.get("icustomerid").toString());
            }
            // 收车地址
            if (!StringUtils.isEmpty(map.get("vcaddress_dest"))) {
                orderOtdLog.setdAddress(map.get("vcaddress_dest").toString());
            }
            // 发车地址
            if (!StringUtils.isEmpty(map.get("vcaddress_origin"))) {
                orderOtdLog.setoAddress(map.get("vcaddress_origin").toString());
            }
            // 收车城市
            if (!StringUtils.isEmpty(map.get("vccity_dest"))) {
                orderOtdLog.setdCity(map.get("vccity_dest").toString());
            }
            // 发车城市
            if (!StringUtils.isEmpty(map.get("vccity_origin"))) {
                orderOtdLog.setoCity(map.get("vccity_origin").toString());
            }
            // 客户名称
            if (!StringUtils.isEmpty(map.get("vccustomer"))) {
                orderOtdLog.setCustomerName(map.get("vccustomer").toString());
            }
            // 经销商名称
            if (!StringUtils.isEmpty(map.get("vcdealername"))) {
                orderOtdLog.setDealerName(map.get("vcdealername").toString());
            }
            // 经销商编号
            if (!StringUtils.isEmpty(map.get("vcdealerno"))) {
                orderOtdLog.setDealerNo(map.get("vcdealerno").toString());
            }
            // 客户订单号
            if (!StringUtils.isEmpty(map.get("vcdmsorderno"))) {
                orderOtdLog.setCustomerOrderNo(map.get("vcdmsorderno").toString());
            }
            // 系统订单号
            if (!StringUtils.isEmpty(map.get("vcdn"))) {
                orderOtdLog.setSysOrderNo(map.get("vcdn").toString());
            }
            // 系统订单号
            if (!StringUtils.isEmpty(map.get("vcdn"))) {
                orderOtdLog.setSysOrderNo(map.get("vcdn").toString());
            }
            // 司机联系方式
            if (!StringUtils.isEmpty(map.get("vcdriver"))) {
                orderOtdLog.setDriverPhone(map.get("vcdriver").toString());
            }
            // 车牌号
            if (!StringUtils.isEmpty(map.get("vclicense"))) {
                orderOtdLog.setLicensePlate(map.get("vclicense").toString());
            }
            // 最新在途位置
            if (!StringUtils.isEmpty(map.get("vclocation"))) {
                orderOtdLog.setNewestPosition(map.get("vclocation").toString());
            }
            // 收车省
            if (!StringUtils.isEmpty(map.get("vcprovince_dest"))) {
                orderOtdLog.setdProvince(map.get("vcprovince_dest").toString());
            }
            // 发车省
            if (!StringUtils.isEmpty(map.get("vcprovince_origin"))) {
                orderOtdLog.setoProvince(map.get("vcprovince_origin").toString());
            }
            // 车型名称
            if (!StringUtils.isEmpty(map.get("vcstylename"))) {
                orderOtdLog.setStyleName(map.get("vcstylename").toString());
            }
            // 车型编码
            if (!StringUtils.isEmpty(map.get("vcstyleno"))) {
                orderOtdLog.setStyleCode(map.get("vcstyleno").toString());
            }
            // 运输方式
            if (!StringUtils.isEmpty(map.get("vctransmode"))) {
                orderOtdLog.setTransportType(map.get("vctransmode").toString());
            }
            // 运输运输方式编码
            if (!StringUtils.isEmpty(map.get("itransmode"))) {
                orderOtdLog.setTransportTypeCode(Integer.valueOf(map.get("itransmode").toString()));
            }
            // 发运类型
            if (!StringUtils.isEmpty(map.get("vctype"))) {
                orderOtdLog.setShipmentType(map.get("vctype").toString());
            }
            // 车架号
            if (!StringUtils.isEmpty(map.get("vcvin"))) {
                orderOtdLog.setVin(map.get("vcvin").toString());
            }
            // 打单时间
            if (!StringUtils.isEmpty(map.get("dtprint"))) {
                orderOtdLog.setPrintOrderTime(simpleDateFormat.parse(map.get("dtprint").toString()));
            }
            // 回单时间
            if (!StringUtils.isEmpty(map.get("dtreturn"))) {
                orderOtdLog.setReturnOrderTime(simpleDateFormat.parse(map.get("dtreturn").toString()));
            }
            // 承运车队名称
            if (!StringUtils.isEmpty(map.get("vcsupplier"))) {
                orderOtdLog.setSupplier(map.get("vcsupplier").toString());
            }
            // 挂起状态，0正常1挂起
            if (!StringUtils.isEmpty(map.get("bsuspend"))) {
                orderOtdLog.setBsuspend(Integer.valueOf(map.get("bsuspend").toString()));
            }

        } catch (Exception e) {
            LOGGER.error("OrderScheduled.analysisOrder ERROR: ", e);
        }

        return orderOtdLog;
    }

    /**
     * 异步抓取 v_jmc_kas_flow_info 数据处理后 放入 kas_order_otd;
     * v_jmc_kas_onway_track数据处理取舍后放入 kas_order_otd_detail
     * 
     * @author: 万磊
     * @param thread 每个线程执行limit(thread,limit)
     * @return void
     */
    @Override
    public void getOrder2(int thread) {
        LOGGER.info("拉取中间表订单====================");
        PushOrderLog pushOrderLog = new PushOrderLog();
        Integer executNum = 0; // 已经执行的数量
        Integer insertNum = 0; // 插入数
        Integer updateNum = 0; // 更新数
        Integer abnormalNum = 0; // 异常数

        // 获取线程名称
        String pushThreadName = Thread.currentThread().getName();
        System.out.println("getOrder2线程名:" + pushThreadName);
        pushOrderLog.setPushThreadName(pushThreadName);
        // 拉取订单（记录拉取日志）
        pushOrderLog.setType(PushOrderLogTypeEnum.ALL.getCode());
        // 开始执行时间
        pushOrderLog.setStartExecutTime(new Date());

        // 定义一次从中间库拿去多少数据
        // 大约1个小时
        // To-Do 应该改为配置文件参数
        int limit = 250;

        EntityWrapper<VJmcKasFlowInfo> entityWrapper = new EntityWrapper<>();
        Wrapper<VJmcKasFlowInfo> wrapper = entityWrapper.eq("bprocess", 0).orderBy("dtrefresh,vcdn");
        List<VJmcKasFlowInfo> vJmcKasFlowInfoList = vJmcKasFlowInfoMapper
                .selectPage(new Page<VJmcKasFlowInfo>(thread, limit), wrapper);

        // 拉取数量
        pushOrderLog.setDataNum(vJmcKasFlowInfoList.size());

        if (vJmcKasFlowInfoList.size() == 0) {
            // 完成时间
            pushOrderLog.setFinshExecutTime(new Date());
            // 为零则不记录执行日志
            // size当为0 时 可能处于无数据状态 休眠1分钟
            // Thread.sleep(60000);
            return;
        }

        // 更新中间表已经获取的数据(bprocess:中间表是否已处理)状态

        for (VJmcKasFlowInfo vJmcKasFlowInfo : vJmcKasFlowInfoList) {
            vJmcKasFlowInfo.setBprocess(1);
        }
        vJmcKasFlowInfoService.updateBatchById(vJmcKasFlowInfoList);

        // 遍历转换成的mao，一一存储进数据库
        LOGGER.info("遍历" + vJmcKasFlowInfoList.size() + "条订单");
        for (int i = 0; i < vJmcKasFlowInfoList.size(); i++) {

            LOGGER.info("遍历第" + i + "条订单");
            String vcdn = vJmcKasFlowInfoList.get(i).getVcdn();

            try {
                OrderOtdLog orderOtdLog = analysisOrder(vJmcKasFlowInfoList.get(i));
                orderOtdLog.setCallUrl(erpUrl.getGetErpKgOrderNo());
                orderOtdLog.setCallStartTime(new Date());
                orderOtdLog.setCallEndTime(new Date());

                // 订单在途跟踪日志明细itf_order_otd_log_detail
                List<OrderOtdLogDetail> orderOtdLogDetailList = new ArrayList<>();

                // 根据vcdn拿到满足条件List<VJmcKasOnwayTrack>
                List<VJmcKasOnwayTrack> vJmcKasOnwayTracks = getOnwayWithRule(vcdn, vJmcKasFlowInfoList.get(i));
                //
                if (vJmcKasOnwayTracks.size() != 0) {
                    for (VJmcKasOnwayTrack vJmcKasOnwayTrack : vJmcKasOnwayTracks) {
                        OrderOtdLogDetail orderOtdLogDetail = analysisOnWayInfo(vJmcKasOnwayTrack);

                        orderOtdLogDetailList.add(orderOtdLogDetail);
                    }
                }

                // 保存订单详细信息、在途信息
                String executWay = saveOrderInfo(orderOtdLog, orderOtdLogDetailList);
                if (executWay.equals("insert")) {
                    insertNum++;
                    pushOrderLog.setInsertNum(insertNum);
                } else if (executWay.equals("update")) {
                    updateNum++;
                    pushOrderLog.setUpdateNum(updateNum);
                }
                executNum++;
                pushOrderLog.setExecutNum(executNum);
                List<PushOrderLog> pushOrderLogList = pushOrderLogService
                        .selectNowDay(PushOrderLogTypeEnum.GF.getCode(), pushThreadName);
                if (CollectionUtils.isEmpty(pushOrderLogList)) {
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.insert(pushOrderLog);
                } else {
                    pushOrderLog.setId(pushOrderLogList.get(0).getId());
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.updateById(pushOrderLog);
                }

            } catch (Exception e) {
                LOGGER.error("拉取订单" + vcdn + "发生异常", e);

                // 保存异常信息
                OrderOtdException orderOtdException = new OrderOtdException();
                orderOtdException.setSysOrderCode(vcdn);
                orderOtdException.setExceptionMsg(JSON.toJSONString(e));
                orderOtdException.setFlag(OrderOtdExceptionEnum.UNTREATED.getCode());
                orderOtdException.setGmtCreate(new Date());
                saveOrderException(orderOtdException);

                abnormalNum++;
                executNum++;
                pushOrderLog.setAbnormalNum(abnormalNum);
                pushOrderLog.setExecutNum(executNum);

                List<PushOrderLog> pushOrderLogList = pushOrderLogService
                        .selectNowDay(PushOrderLogTypeEnum.GF.getCode(), pushThreadName);
                if (CollectionUtils.isEmpty(pushOrderLogList)) {
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.insert(pushOrderLog);
                } else {
                    pushOrderLog.setId(pushOrderLogList.get(0).getId());
                    // 完成时间
                    pushOrderLog.setFinshExecutTime(new Date());
                    // 记录执行日志
                    pushOrderLogService.updateById(pushOrderLog);
                }

                continue;

            }

        }

    }

    /*
     * @Description: 从中间表取符合规则的onway信息
     * 
     * @Author: zharui
     */
    private List<VJmcKasOnwayTrack> getOnwayWithRule(String dn, VJmcKasFlowInfo info) {
        EntityWrapper<VJmcKasOnwayTrack> queryWrapper = new EntityWrapper<>();
        Wrapper<VJmcKasOnwayTrack> whereWrapper = queryWrapper.eq("vcdn", dn).isNotNull("dtlocation")
                .addFilter(" (vcprovince is not null or VCLONGITUDE is not null)");
        // 只处理定位时间小于主数据更新时间3天内的
        // if (!StringUtils.isEmpty(info.getDtrefresh())) {
        // whereWrapper.ge("dtlocation", DateUtils.addDays(info.getDtrefresh(), -3));
        // }
        // 只处理小于运抵时间的
        if (!StringUtils.isEmpty(info.getDtdelivery())) {
            whereWrapper.le("dtlocation", info.getDtdelivery());
        }
        // 只处理大于调度指令时间的
        if (!StringUtils.isEmpty(info.getDtassign())) {
            whereWrapper.ge("dtlocation", info.getDtassign());
        }
        whereWrapper.orderBy("dtlocation asc");
        return vJmcKasOnwayTrackMapper.selectList(whereWrapper);
    }

    /* @author:万磊 */
    @Override
    public OrderOtdLog analysisOrder(VJmcKasFlowInfo vJmcKasFlowInfo) {
        OrderOtdLog orderOtdLog = new OrderOtdLog();
        // 离昌时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtonway())) {
            orderOtdLog.setLeaveTime(vJmcKasFlowInfo.getDtonway());
        }
        // 安排运力时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtassign())) {
            orderOtdLog.setArrangeCapacityTime(vJmcKasFlowInfo.getDtassign());
        }
        // 入铁路库时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDt2rail())) {
            orderOtdLog.setEnterRailwayTime(vJmcKasFlowInfo.getDt2rail());
        }
        // 入中转库时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtcache())) {
            orderOtdLog.setInboundTime(vJmcKasFlowInfo.getDtcache());
        }
        // 订单创建时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtcreate())) {
            orderOtdLog.setOrderCreateTime(vJmcKasFlowInfo.getDtcreate());
        }
        // 运抵时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtdelivery())) {
            orderOtdLog.setShiptoTime(vJmcKasFlowInfo.getDtdelivery());
        }
        // 最新在途时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtlocation())) {
            orderOtdLog.setNewestTime(vJmcKasFlowInfo.getDtlocation());
        }
        // 订单日期
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtorder())) {
            orderOtdLog.setOrderDate(vJmcKasFlowInfo.getDtorder());
        }
        // 出中联库时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtout3pl())) {
            orderOtdLog.setOutboundTime(vJmcKasFlowInfo.getDtout3pl());
        }
        // 提车时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtoutFactory())) {
            orderOtdLog.setPickTime(vJmcKasFlowInfo.getDtoutFactory());
        }
        // 装车时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtload())) {
            orderOtdLog.setLoadTime(vJmcKasFlowInfo.getDtload());
        }
        // 客户名称
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVccustomer())) {
            orderOtdLog.setCustomerName(vJmcKasFlowInfo.getVccustomer());
        }
        // 客户编号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getIcustomerid())) {
            orderOtdLog.setCustomerNo(String.valueOf(vJmcKasFlowInfo.getIcustomerid()));
        }
        // 运输方式
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getItransmode())) {
            orderOtdLog.setTransportType(vJmcKasFlowInfo.getVctransmode());
        }
        // 运输运输方式编码
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVctransmode())) {
            orderOtdLog.setTransportTypeCode(Integer.valueOf(vJmcKasFlowInfo.getItransmode()));
        }
        // 收车地址
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcaddressDest())) {
            orderOtdLog.setdAddress(vJmcKasFlowInfo.getVcaddressDest());
        }
        // 发车地址
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcaddressOrigin())) {
            orderOtdLog.setoAddress(vJmcKasFlowInfo.getVcaddressOrigin());
        }
        // 收车城市
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcaddressOrigin())) {
            orderOtdLog.setdCity(vJmcKasFlowInfo.getVccityDest());
        }
        // 发车城市
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVccityOrigin())) {
            orderOtdLog.setoCity(vJmcKasFlowInfo.getVccityOrigin());
        }
        // 经销商名称
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcdealername())) {
            orderOtdLog.setDealerName(vJmcKasFlowInfo.getVcdealername());
        }
        // 经销商编号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcdealerno())) {
            orderOtdLog.setDealerNo(vJmcKasFlowInfo.getVcdealerno());
        }
        // 客户订单号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcdmsorderno())) {
            orderOtdLog.setCustomerOrderNo(vJmcKasFlowInfo.getVcdmsorderno());
        }
        // 系统订单号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcdn())) {
            orderOtdLog.setSysOrderNo(vJmcKasFlowInfo.getVcdn());
        }
        // 司机联系方式
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcdriver())) {
            orderOtdLog.setDriverPhone(vJmcKasFlowInfo.getVcdriver());
        }
        // 车牌号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVclicense())) {
            orderOtdLog.setLicensePlate(vJmcKasFlowInfo.getVclicense());
        }
        // 最新在途位置
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVclocation())) {
            orderOtdLog.setNewestPosition(vJmcKasFlowInfo.getVclocation());
        }
        // 收车省
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcprovinceDest())) {
            orderOtdLog.setdProvince(vJmcKasFlowInfo.getVcprovinceDest());
        }
        // 发车省
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcprovinceOrigin())) {
            orderOtdLog.setoProvince(vJmcKasFlowInfo.getVcprovinceOrigin());
        }
        // 车型名称
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcstylename())) {
            orderOtdLog.setStyleName(vJmcKasFlowInfo.getVcstylename());
        }
        // 车型编码
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcstyleno())) {
            orderOtdLog.setStyleCode(vJmcKasFlowInfo.getVcstyleno());
        }

        // 发运类型
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVctype())) {
            orderOtdLog.setShipmentType(vJmcKasFlowInfo.getVctype());
        }
        // 车架号
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcvin())) {
            orderOtdLog.setVin(vJmcKasFlowInfo.getVcvin());
        }
        // 打单时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtprint())) {
            orderOtdLog.setPrintOrderTime(vJmcKasFlowInfo.getDtprint());
        }
        // 回单时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getDtreturn())) {
            orderOtdLog.setReturnOrderTime(vJmcKasFlowInfo.getDtreturn());
        }
        // 承运车队名称
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getVcsupplier())) {
            orderOtdLog.setSupplier(vJmcKasFlowInfo.getVcsupplier());
        }
        // 挂起状态，0正常1挂起
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getBsuspend())) {
            orderOtdLog.setBsuspend(vJmcKasFlowInfo.getBsuspend());
        }
        // 临牌
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getTempLicense())) {
            orderOtdLog.setTempLicense(vJmcKasFlowInfo.getTempLicense());
        }
        // 首次挂起时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getSuspendTime())) {
            orderOtdLog.setSuspendTime(vJmcKasFlowInfo.getSuspendTime());
        }
        // 末次解挂时间
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getResumeTime())) {
            orderOtdLog.setResumeTime(vJmcKasFlowInfo.getResumeTime());
        }
        // 挂起类型
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getSuspType())) {
            orderOtdLog.setSuspType(vJmcKasFlowInfo.getSuspType());
        }
        // 挂起备注
        if (!StringUtils.isEmpty(vJmcKasFlowInfo.getSuspMemo())) {
            orderOtdLog.setSuspMemo(vJmcKasFlowInfo.getSuspMemo());
        }
        return orderOtdLog;
    }

    /* @author:万磊 */
    @Override
    public OrderOtdLogDetail analysisOnWayInfo(VJmcKasOnwayTrack vJmcKasOnwayTrack) {
        OrderOtdLogDetail orderOtdLogDetail = new OrderOtdLogDetail();
        // 明细 id
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getTid())) {
            orderOtdLogDetail.settId(String.valueOf(vJmcKasOnwayTrack.getTid()));
        }
        // 在途时间
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getDtlocation())) {
            orderOtdLogDetail.setTrackTime(vJmcKasOnwayTrack.getDtlocation());
        }
        // 所在省
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVcprovince())) {
            orderOtdLogDetail.setProvince(vJmcKasOnwayTrack.getVcprovince());
        }
        // 所在市
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVccity())) {
            orderOtdLogDetail.setCity(vJmcKasOnwayTrack.getVccity());
        }
        // 所在区/县
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVcarea())) {
            orderOtdLogDetail.setArea(vJmcKasOnwayTrack.getVcarea());
        }
        // 详细地址
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVclocation())) {
            orderOtdLogDetail.setAddress(vJmcKasOnwayTrack.getVclocation());
        }
        // 经度
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVclongitude())) {
            orderOtdLogDetail.setLongitude(new BigDecimal(vJmcKasOnwayTrack.getVclongitude()));
        }
        // 纬度
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVclatitude())) {
            orderOtdLogDetail.setLatitude(new BigDecimal(vJmcKasOnwayTrack.getVclatitude()));
        }
        // 系统订单号
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVcdn())) {
            orderOtdLogDetail.setSysOrderNo(vJmcKasOnwayTrack.getVcdn());
        }
        // 路由模式
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getIsrcType())) {
            orderOtdLogDetail.setSrcType(vJmcKasOnwayTrack.getIsrcType());
        }
        // 承运车
        if (!StringUtils.isEmpty(vJmcKasOnwayTrack.getVcshiper())) {
            orderOtdLogDetail.setShiper(vJmcKasOnwayTrack.getVcshiper());
        }
        return orderOtdLogDetail;
    }

    /*
     * 判断某笔运单信息是否需要更新 数据来源非erp且运抵时间不为空时则不更新数据
     * 
     * @author:查睿
     * 
     * @return 可更新则返回false,不可更新则返回true
     */
    @Override
    public boolean isNotRequireUpdate(List<OrderOtd> kasDataStatus) {
        if (null == kasDataStatus || CollectionUtils.isEmpty(kasDataStatus)
                || StringUtils.isEmpty(kasDataStatus.get(0).getWay())) {
            return false;
        } else {
            if (!OrderWayEnum.WAY_SYS_INTF.getCode().equalsIgnoreCase(kasDataStatus.get(0).getWay())
                    && !StringUtils.isEmpty(kasDataStatus.get(0).getShiptoTime())) {
                return true;
            } else {
                return false;
            }
        }
    }

    @Override
    @Transactional
    public void dealMiddle(List<VJmcKasFlowInfo> vJmcKasFlowInfoList) {
        if (null == vJmcKasFlowInfoList || vJmcKasFlowInfoList.isEmpty() || vJmcKasFlowInfoList.size() <= 0) {
            return;
        }

        PushOrderLog pushOrderLog = new PushOrderLog();
        Integer executNum = 0; // 已经执行的数量
        Integer insertNum = 0; // 插入数
        Integer updateNum = 0; // 更新数
        Integer abnormalNum = 0; // 异常数
        int ignoreNum = 0; // 忽略数

        // 获取线程名称
        String pushThreadName = Thread.currentThread().getName();
        pushOrderLog.setPushThreadName(pushThreadName);
        // 拉取订单（记录拉取日志）
        pushOrderLog.setType(PushOrderLogTypeEnum.ALL.getCode());
        // 开始执行时间
        pushOrderLog.setStartExecutTime(new Date());

        // 拉取数量
        pushOrderLog.setDataNum(vJmcKasFlowInfoList.size());

        // 遍历转换成的mao，一一存储进数据库
        LOGGER.debug("遍历共" + vJmcKasFlowInfoList.size() + "条订单");
        for (int i = 0; i < vJmcKasFlowInfoList.size(); i++) {

            LOGGER.debug("遍历第" + i + "条订单");
            String vcdn = vJmcKasFlowInfoList.get(i).getVcdn();

            try {
                OrderOtdLog orderOtdLog = analysisOrder(vJmcKasFlowInfoList.get(i));
                orderOtdLog.setCallUrl(erpUrl.getGetErpKgOrderNo());
                orderOtdLog.setCallStartTime(new Date());
                orderOtdLog.setCallEndTime(new Date());

                // 订单在途跟踪日志明细itf_order_otd_log_detail
                List<OrderOtdLogDetail> orderOtdLogDetailList = new ArrayList<>();

                // 根据vcdn拿到满足条件List<VJmcKasOnwayTrack>
                List<VJmcKasOnwayTrack> vJmcKasOnwayTracks = getOnwayWithRule(vcdn, vJmcKasFlowInfoList.get(i));
                //
                if (vJmcKasOnwayTracks.size() != 0) {
                    for (VJmcKasOnwayTrack vJmcKasOnwayTrack : vJmcKasOnwayTracks) {
                        OrderOtdLogDetail orderOtdLogDetail = analysisOnWayInfo(vJmcKasOnwayTrack);

                        orderOtdLogDetailList.add(orderOtdLogDetail);
                    }
                }

                // 保存订单详细信息、在途信息
                String executWay = saveOrderInfo(orderOtdLog, orderOtdLogDetailList);
                if (executWay.equals("insert")) {
                    insertNum++;
                } else if (executWay.equals("update")) {
                    updateNum++;
                } else if ("ignore".equalsIgnoreCase(executWay)) {
                    ignoreNum++;
                }
                executNum++;
            } catch (Exception e) {
                LOGGER.error("处理中间表DN " + vcdn + "发生异常", e);

                // 保存异常信息
                OrderOtdException orderOtdException = new OrderOtdException();
                orderOtdException.setSysOrderCode(vcdn);
                orderOtdException.setExceptionMsg(JSON.toJSONString(e));
                orderOtdException.setFlag(OrderOtdExceptionEnum.UNTREATED.getCode());
                orderOtdException.setGmtCreate(new Date());
                saveOrderException(orderOtdException);

                abnormalNum++;
                executNum++;
            }
        }

        pushOrderLog.setExecutNum(executNum);
        pushOrderLog.setAbnormalNum(abnormalNum);
        pushOrderLog.setUpdateNum(updateNum);
        pushOrderLog.setInsertNum(insertNum);
        pushOrderLog.setIgnoreNum(ignoreNum);

        // 完成时间
        pushOrderLog.setFinshExecutTime(new Date());
        // 记录执行日志
        pushOrderLogService.insert(pushOrderLog);

        // 更新中间表已经获取的数据(bprocess:中间表是否已处理)状态
        for (VJmcKasFlowInfo vJmcKasFlowInfo : vJmcKasFlowInfoList) {
            vJmcKasFlowInfo.setBprocess(1);
        }
        vJmcKasFlowInfoService.updateBatchById(vJmcKasFlowInfoList);
    }

    @Override
    public List<OrderOtd> getNeedRefreshOrders() {
        EntityWrapper<OrderOtd> qWrapper = new EntityWrapper<OrderOtd>();
        qWrapper.addFilter(" shipto_time is null").addFilter(" pick_time>'2019-4-1'")
                .addFilter(" gmt_modified<current_date ").addFilter(" customer_name like '%股份%' ");
        return orderOtdService.selectList(qWrapper);
    }

}
